"use strict";

const fs = require('fs');
const path = require('path');
const shelljs = require('shelljs');
const gulp = require("gulp");
const ts = require("gulp-typescript");
const through2 = require("through2");
const postcss = require('gulp-postcss');
const babel = require('gulp-babel');
const glob = require("glob");
const merge2 = require('merge2');
const getBabelConfig = require("./config/getBabelConfig");
const { compilerOptions: tsConfig} = require('./tsconfig.json');
const replaceLib = require('./scripts/replaceLib');
const resolveCwd = require('./scripts/resolveCwd');

const pkg = require(resolveCwd('package.json'));
const tsDefaultReporter = ts.reporter.defaultReporter();
const lessPath = new RegExp(`(["']${pkg.name})/assets/([^.'"]+).less`, 'g');

function babelifyInternal(js, modules) {
  function replacer(match, m1, m2) {
    return `${m1}/assets/${m2}.css`;
  }

  const babelConfig = getBabelConfig(modules);
  if (modules === false) {
    babelConfig.plugins.push(replaceLib);
  }

  let stream = js.pipe(babel(babelConfig));
  // if (argv.compress) {
  //   stream = stream.pipe(minify());
  // }
  return stream
    .pipe(
      through2.obj(function(file, encoding, next) {
        const contents = file.contents
          .toString(encoding)
          .replace(lessPath, replacer);
        file.contents = Buffer.from(contents);
        this.push(file);
        next();
      })
    )
    .pipe(gulp.dest(modules !== false ? "lib" : "es"));
}

function babelify(modules) {
  try {
    const streams = [];
    const assets = gulp
      .src(['src/**/*.@(png|svg|less|d.ts)'])
      .pipe(gulp.dest(modules === false ? "es" : "lib"));
    if (
      glob.sync("src/**/*.{ts,tsx}").length &&
      !glob.sync("src/**/*.d.ts").length
    ) {
      let error = 0;
      let reporter = tsDefaultReporter;
      const tsResult = gulp
        .src(['src/**/*.ts', 'src/**/*.tsx', "typings/**/*.d.ts"])
        .pipe(ts(tsConfig, reporter));

      const check = () => {
        if (error) {
          console.error("compile error", error);
          process.exit(1);
        }
      };
      tsResult.on("finish", check);
      tsResult.on("end", check);

      streams.push(
        tsResult.dts
          // .pipe(require('gulp-debug')())
          .pipe(gulp.dest(modules === false ? "es" : "lib"))
      );
      streams.push(babelifyInternal(tsResult.js, modules));
    } else {
      streams.push(
        babelifyInternal(
          gulp.src([`${src}/**/*.js`, `${src}/**/*.jsx`]),
          modules
        )
      );
    }
    return merge2(streams.concat([assets]));
  } catch (err) {
    console.log(err);
  }
}

function cleanCompile() {
  try {
    if (fs.existsSync(resolveCwd('lib'))) {
      shelljs.rm('-rf', resolveCwd('lib'));
    }
    if (fs.existsSync(resolveCwd('es'))) {
      shelljs.rm('-rf', resolveCwd('es'));
    }
    if (fs.existsSync(resolveCwd('assets'))) {
      shelljs.rm('-rf', resolveCwd('assets/*.css'));
    }
  } catch (err) {
    console.log('Clean up failed:', err);
    throw err;
  }
}

gulp.task(
  'cleanCompile',
  gulp.series(done => {
    cleanCompile();
    done();
  })
);

gulp.task("js", () => {
  console.log("[Parallel] compile js...");
  return babelify();
});

gulp.task('es', () => {
  console.log('[Parallel] compile es...');
  return babelify(false);
});

gulp.task('css', () => {
  const less = require('gulp-less');
  return gulp
    .src('assets/*.less')
    .pipe(less({
      javascriptEnabled: true
    }))
    .pipe(postcss([require('./scripts/getAutoprefixer')()]))
    .pipe(gulp.dest('assets'));
});

gulp.task('compile', gulp.series('cleanCompile', gulp.parallel('js', 'es', 'css')));
